<!-- =================================================================== -->
<!-- ==     重构后的 BucketContentsPage.vue (行数 < 300)     == -->
<!-- =================================================================== -->
<template>
    <div class="bucket-contents-page" v-loading="isLoading">
        <!-- 1. 页面头部和面包屑导航 (保留) -->
        <div class="unified-nav-bar">
            <el-button @click="goBack" :icon="ArrowLeft" text class="back-button-unified" />
            <el-breadcrumb :separator-icon="ArrowRight">
                <el-breadcrumb-item :to="{ name: 'BucketList' }">Bucket 列表</el-breadcrumb-item>
                <el-breadcrumb-item>
                    <router-link v-if="path" :to="{ name: 'BucketContents', params: { bucketName: bucketName } }">
                        {{ bucketName }}
                    </router-link>
                    <span v-else>{{ bucketName }}</span>
                </el-breadcrumb-item>
                <el-breadcrumb-item v-for="(part, index) in breadcrumbParts" :key="index">
                    <router-link v-if="index < breadcrumbParts.length - 1" :to="part.route">
                        {{ part.name }}
                    </router-link>
                    <span v-else>{{ part.name }}</span>
                </el-breadcrumb-item>
            </el-breadcrumb>
        </div>

        <!-- 2. 操作栏 (使用新组件) -->
        <ObjectActionBar :bucket-name="bucketName" :current-path="currentPath" :search-prefix="searchPrefix"
            :show-versions="showVersions" :is-versioning-enabled="isVersioningEnabled" :selected-items="selectedItems"
            @create-folder="openCreateFolderDrawer" @refresh="fetchBucketContents" @search="handleSearch"
            @toggle-versions="handleToggleVersions" @openFragmentManagement="openFragmentManagementDrawer" />

        <!-- 3. 表格 (使用新组件) -->
        <ObjectTable ref="objectTableRef" :table-data="tableData" :is-versioning-enabled="isVersioningEnabled"
            :show-versions="showVersions" :bucket-name="bucketName" @selection-change="handleSelectionChange"
            @navigate="navigateToPath" @detail="openDetailDrawer" @delete="handleSingleDelete" @restore="handleRestore"
            @row-selection-change="handleRowSelectionChange" @action-completed="fetchBucketContents"
            @sort-change="handleSortChange" />

        <!-- 4. 批量操作栏和分页 (使用新组件) -->
        <ObjectBatchActionBar :selected-items="selectedItems" :total-items="selectableItemsCount"
            :is-all-selected="isAllSelected" :is-indeterminate="isIndeterminate" :pagination="pagination"
            :is-downloading="isDownloading" :table-el="objectTableRef?.$el" :is-versioning-enabled="isVersioningEnabled"
            :show-versions="showVersions" :bucket-name="bucketName" @select-all-change="handleSelectAllChange"
            @batch-delete="handleBatchDelete" @batch-restore="handleBatchRestore" @size-change="handleSizeChange"
            @current-change="handleCurrentChange" />
        <!-- 5. 所有抽屉和对话框 (保留) -->
        <CreateFolderDrawer v-model:visible="showCreateFolderDrawer" :bucket-name="bucketName"
            :current-path="currentPath" @success="fetchBucketContents" />
        <ObjectDetailDrawer v-model:visible="isDetailDrawerVisible" :bucket-name="bucketName"
            :object-key="selectedObjectKey" />

        <FragmentManagementDrawer ref="fragmentDrawerRef" v-if="isFragmentDrawerVisible"
            v-model:visible="isFragmentDrawerVisible" :bucket-name="bucketName" />
    </div>
</template>

<script setup>
// --- 1. Imports ---
import { ref, computed, watch, onMounted, h } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import apiClient from '@/api/index.js';
// import { api } from '@/api';
import { ElMessage, ElMessageBox, ElLoading, ElNotification } from 'element-plus';
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue';
import { getBaseName } from '@/utils/formatters.js';
import { secureBatchDownload } from '@/utils/downloadHelper'; // 【新增】导入批量下载助手

// 导入新的子组件
import ObjectActionBar from '@/components/BucketContents/ObjectActionBar.vue';
import ObjectTable from '@/components/BucketContents/ObjectTable.vue';
import ObjectBatchActionBar from '@/components/BucketContents/ObjectBatchActionBar.vue';

// 导入抽屉组件
import CreateFolderDrawer from '@/components/CreateFolderDrawer.vue';
import ObjectDetailDrawer from '@/components/ObjectDetailDrawer.vue';

import FragmentManagementDrawer from '@/components/FragmentManagementDrawer.vue';

// --- 2. Props, State & Refs ---
const props = defineProps({
    bucketName: { type: String, required: true },
    path: { type: [String, Array], default: '' },
});
const router = useRouter();
const route = useRoute();

const isLoading = ref(true);
const tableData = ref([]);
const selectedItems = ref([]);
const searchPrefix = ref('');
const currentPath = ref('');
const pagination = ref({ currentPage: 1, pageSize: 50, total: 0 });
const isDownloading = ref(false);
const showCreateFolderDrawer = ref(false);
const isDetailDrawerVisible = ref(false);
const selectedObjectKey = ref('');
// 【新增】下面这两行是新加的
const showVersions = ref(route.query.versions === 'true'); // 控制“显示历史版本”开关的状态
const isVersioningEnabled = ref(false); // 存储当前Bucket的版本控制是否已开启
const objectTableRef = ref(null); // 用于获取 ObjectTable 组件实例
const isFragmentDrawerVisible = ref(false);

const fragmentDrawerRef = ref(null);

const sortInfo = ref({
    prop: null, // 'name', 'size', 'date_modified'
    order: null // 'ascending', 'descending'
});

// --- 3. Computed Properties ---
const breadcrumbParts = computed(() => {
    if (!props.path || props.path.length === 0) {
        return [];
    }

    // 1. 确保我们总是处理一个干净的路径段数组
    const pathSegments = Array.isArray(props.path)
        ? props.path
        : props.path.replace(/\/$/, '').split('/').filter(p => p);

    // 2. 为每个路径段生成面包屑项
    return pathSegments.map((segment, index) => {
        // a. 计算出到达当前环节所需要的所有路径段的【数组】
        const targetPathArray = pathSegments.slice(0, index + 1);

        // b. 构造路由对象
        return {
            name: segment, // 显示的名称
            route: {
                name: 'BucketContentsWithPath', // 目标路由名
                params: {
                    bucketName: props.bucketName,
                    path: targetPathArray // 【正确】传递的是路径段数组
                }
            }
        };
    });
});

// 【新增】这些计算属性是状态同步的关键
const selectableItemsCount = computed(() => {
    // 总的可勾选项目数，不包括文件名标题行
    return tableData.value.filter(item => !item.is_header_row).length;
});

const selectedSelectableItemsCount = computed(() => {
    // 已选中的可勾选项目数
    return selectedItems.value.filter(item => !item.is_header_row).length;
});

const isAllSelected = computed(() => {
    // 是否全选
    const total = selectableItemsCount.value;
    const selected = selectedSelectableItemsCount.value;
    return total > 0 && selected === total;
});

const isIndeterminate = computed(() => {
    // 是否半选
    const selected = selectedSelectableItemsCount.value;
    return selected > 0 && !isAllSelected.value;
});

// 【新增】这个新函数
const fetchBucketDetails = async () => {
    if (!props.bucketName) return;
    try {
        // 调用后端新API
        const response = await apiClient.get(`/api/v1/buckets/${props.bucketName}/details`);
        // 根据后端返回的字符串更新状态
        isVersioningEnabled.value = response.data.versioning === '已开启';
    } catch (error) {
        console.error("无法获取存储桶详情:", error);
        isVersioningEnabled.value = false; // 如果获取失败，安全起见，默认未开启
        ElMessage.error("获取存储桶版本状态失败");
    }
};

// 在 /src/views/BucketContentsPage.vue 的 <script setup> 中

// 【核心修复】用这个最终的、正确的函数替换旧的 processRawDataForTable
const processRawDataForTable = (items) => {
    if (!items || !Array.isArray(items)) return [];
    const flatList = [];

    items.forEach(latestVersion => {
        // 文件夹只占一行
        if (latestVersion.type === 'folder') {
            flatList.push({
                ...latestVersion,
                is_header_row: false,
                unique_key: latestVersion.name,
            });
            return;
        }

        // --- 文件组处理 ---
        // 1. 添加“文件名”标题行
        flatList.push({
            type: 'header',
            name: latestVersion.name,
            date_modified: latestVersion.date_modified,
            is_header_row: true,
            group_key: latestVersion.name,
            unique_key: `${latestVersion.name}#header`,
            // 把所有版本信息都挂载到标题行上，方便联动勾选
            versions: [latestVersion, ...(latestVersion.history || [])],
        });

        // 2. 添加最新版本行
        flatList.push({
            ...latestVersion,
            history: undefined, // 清理掉，不再需要
            is_header_row: false,
            group_key: latestVersion.name,
            unique_key: `${latestVersion.name}#${latestVersion.version_id}`,
        });

        // 3. 添加所有历史版本行
        if (latestVersion.history && latestVersion.history.length > 0) {
            latestVersion.history.forEach(historicalVersion => {
                flatList.push({
                    ...historicalVersion,
                    is_header_row: false,
                    group_key: latestVersion.name,
                    unique_key: `${historicalVersion.name}#${historicalVersion.version_id}`,
                });
            });
        }
    });

    return flatList;
};

// 在 /src/views/BucketContentsPage.vue 的 <script setup> 中

const handleRowSelectionChange = (selection, row) => {
    // 检查子组件的 ref 是否存在
    if (!objectTableRef.value) return;

    // 【修改】获取内部的 el-table 实例
    const internalTable = objectTableRef.value.getTableRef();
    if (!internalTable) return; // 如果实例获取不到，也直接返回

    // 检查被点击的行是否为“文件名”标题行
    if (row.is_header_row) {
        const isSelected = selection.some(item => item.unique_key === row.unique_key);
        const versionsInGroup = row.versions || [];

        versionsInGroup.forEach(versionToToggle => {
            const targetRow = tableData.value.find(
                item => !item.is_header_row && item.version_id === versionToToggle.version_id
            );

            if (targetRow) {
                // 【修改】通过获取到的 internalTable 实例来调用方法
                internalTable.toggleRowSelection(targetRow, isSelected);
            }
        });
    }
};

// 在 /src/views/BucketContentsPage.vue 的 <script setup> 中

const fetchBucketContents = async () => {
    isLoading.value = true;
    try {
        const pathFromRoute = Array.isArray(route.params.path) ? route.params.path.join('/') : (route.params.path || '');
        currentPath.value = pathFromRoute ? pathFromRoute + (pathFromRoute.endsWith('/') ? '' : '/') : '';

        // 【核心】在这里构建请求参数，包含 versions 标志
        const params = {
            page: pagination.value.currentPage,
            limit: pagination.value.pageSize,
            search: searchPrefix.value,
            // 直接使用 showVersions 的当前状态
            versions: showVersions.value,
        };

        // 发起API请求
        const response = await apiClient.get(`/api/v1/buckets/${props.bucketName}/${currentPath.value}`, { params });

        // 【核心】根据 showVersions 的状态，决定如何处理返回的数据
        if (showVersions.value) {
            // 如果是“显示版本”模式，调用“拍平”函数
            tableData.value = processRawDataForTable(response.data.items);
        } else {
            // 如果是“隐藏版本”模式，后端返回的就是普通列表，直接使用
            // 只需要添加 unique_key 即可
            tableData.value = response.data.items.map(item => ({
                ...item,
                unique_key: item.version_id || item.name
            }));
        }

        pagination.value.total = response.data.total;

    } catch (error) {
        ElMessage.error('获取文件列表失败！');
        tableData.value = [];
    } finally {
        isLoading.value = false;
    }
};

const goBack = () => {
    router.back(); // router.back() 会自动处理查询参数，更简单健壮
};

const navigateToPath = (path) => {
    router.push({
        name: 'BucketContentsWithPath',
        params: { bucketName: props.bucketName, path: path ? path.split('/').filter(p => p) : [] },
        // 【关键】在导航时，把当前的 versions 状态也带过去
        query: { versions: showVersions.value ? 'true' : undefined }
    });
};

const handleSearch = (newPrefix) => {
    searchPrefix.value = newPrefix;
    pagination.value.currentPage = 1;
    fetchBucketContents();
};

const handleSizeChange = (newPageSize) => {
    pagination.value.pageSize = newPageSize;
    pagination.value.currentPage = 1;
    fetchBucketContents();
};

const handleCurrentChange = (newPage) => {
    pagination.value.currentPage = newPage;
    fetchBucketContents();
};

// 在 /src/views/BucketContentsPage.vue 的 <script setup> 中

// 【最终版】替换 handleSelectionChange
const handleSelectionChange = (selection) => {
    // 更新父组件的 selectedItems，用于批量操作栏
    selectedItems.value = selection;

    // --- 状态向上同步逻辑 (无半选状态版) ---
    const headerRows = tableData.value.filter(item => item.is_header_row);

    headerRows.forEach(header => {
        const versionsInGroup = header.versions || [];
        const totalVersionCount = versionsInGroup.length;

        // 筛选出当前选中的、属于这个组的版本
        const selectedVersions = selection.filter(
            sel => sel.group_key === header.group_key && !sel.is_header_row
        );
        const selectedVersionCount = selectedVersions.length;

        // 获取标题行在 tableData 中的真实对象引用
        const headerRowInTable = tableData.value.find(item => item.unique_key === header.unique_key);
        if (!headerRowInTable) return;

        // 【核心逻辑】判断是否全选
        if (selectedVersionCount === totalVersionCount && totalVersionCount > 0) {
            // 如果全选了，确保标题行在 el-table 内部也是选中状态
            objectTableRef.value?.getTableRef().toggleRowSelection(headerRowInTable, true);
        } else {
            // 只要不是全选，就确保标题行是未选中状态
            objectTableRef.value?.getTableRef().toggleRowSelection(headerRowInTable, false);
        }
    });
};

const handleSortChange = ({ prop, order }) => {
    // 更新排序状态
    sortInfo.value = { prop, order };

    // 【关键】调用我们现有的数据获取函数
    // 因为纯前端排序只需要对当前页数据进行，所以不需要重新从API获取
    // 我们直接对 tableData.value 进行排序
    sortCurrentTableData();
};

// 【新增代码】一个专门用于前端排序的函数
const sortCurrentTableData = () => {
    const { prop, order } = sortInfo.value;

    // 如果没有排序规则，则不执行任何操作
    if (!prop || !order) {
        return;
    }

    tableData.value.sort((a, b) => {
        // 基础排序规则：文件夹和标题行总是在最前面
        const isSpecialA = a.type === 'folder' || a.is_header_row;
        const isSpecialB = b.type === 'folder' || b.is_header_row;
        if (isSpecialA && !isSpecialB) return -1;
        if (!isSpecialA && isSpecialB) return 1;

        // 如果两个都是特殊行，按名称排序
        if (isSpecialA && isSpecialB) {
            return a.name.localeCompare(b.name);
        }

        // 对于普通文件行，按指定的属性排序
        let valA, valB;

        switch (prop) {
            case 'name':
                // 在版本视图下，我们应该按 group_key (主文件名) 排序，而不是完整的 name
                valA = (a.group_key || a.name).toLowerCase();
                valB = (b.group_key || b.name).toLowerCase();
                break;
            case 'size':
                valA = parseSizeToBytes(a.size);
                valB = parseSizeToBytes(b.size);
                break;
            case 'date_modified':
                // 将 ISO 8601 格式的日期字符串转换为 Date 对象
                // new Date() 可以正确解析这种格式
                // 如果 date_modified 可能为 null 或 undefined，使用 0 作为备用值
                valA = a.date_modified ? new Date(a.date_modified).getTime() : 0;
                valB = b.date_modified ? new Date(b.date_modified).getTime() : 0;
                break;
            default:
                return 0;
        }

        if (valA < valB) {
            return order === 'ascending' ? -1 : 1;
        }
        if (valA > valB) {
            return order === 'ascending' ? 1 : -1;
        }
        return 0;
    });
};

// 【新增代码】从上次回复中复制过来的辅助函数
const parseSizeToBytes = (sizeStr) => {
    if (!sizeStr || typeof sizeStr !== 'string') return 0;
    if (sizeStr === '-') return 0;
    const units = { 'B': 1, 'KB': 1024, 'MB': 1024 ** 2, 'GB': 1024 ** 3, 'TB': 1024 ** 4 };
    const parts = sizeStr.trim().split(' ');
    if (parts.length < 2) return 0;
    const value = parseFloat(parts[0]);
    const unit = parts[1].toUpperCase();
    return value * (units[unit] || 1);
}

const handleSelectAllChange = (checked) => {
    // 【修改】我们不再依赖子组件暴露的方法，而是直接操作 ref
    if (objectTableRef.value) {
        // 调用子组件暴露的 getTableRef 方法获取 el-table 实例
        const internalTable = objectTableRef.value.getTableRef();
        if (internalTable) {
            internalTable.toggleAllSelection();
        }
    }
};

const openDetailDrawer = (row) => {
    if (row.type === 'file') {
        selectedObjectKey.value = row.name;
        isDetailDrawerVisible.value = true;
    } else {
        ElMessage.info('文件夹暂无详情视图');
    }
};

const openCreateFolderDrawer = () => {
    showCreateFolderDrawer.value = true;
};

const executeDownload = async (items) => {
    if (items.length === 1 && !items[0].endsWith('/')) {
        const downloadUrl = `${apiClient.defaults.baseURL}/api/v1/download?bucket_name=${encodeURIComponent(props.bucketName)}&path=${encodeURIComponent(items[0])}`;
        const link = document.createElement('a');
        link.href = downloadUrl;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        return;
    }
    isDownloading.value = true;
    const msg = ElMessage({ message: '正在准备打包下载...', type: 'info', duration: 0 });
    try {
        await api.s3.downloadBucketItems(props.bucketName, items, props.path);
    } catch (error) {
        ElMessage.error(error.message || '准备下载失败');
    } finally {
        msg.close();
        isDownloading.value = false;
    }
};

// const handleSingleDownload = (row) => executeDownload([row.name]);
// const handleBatchDownload = () => executeDownload(selectedItems.value.map(item => item.name));
// const handleBatchDownload = (items) => {
//     // items 会由子组件 emit 过来，但更简单的做法是让子组件自己处理
//     secureBatchDownload(props.bucketName, selectedItems.value);
// }

// 在 /src/views/BucketContentsPage.vue 的 <script setup> 中

const confirmAndDelete = (item) => {
    if (!item) return;

    let confirmTitle = '';
    let messageVNode; // 我们将使用 VNode 来构建消息
    let apiCall;

    if (showVersions.value) {
        // --- “显示历史版本”模式下：执行彻底删除 ---
        confirmTitle = '彻底删除';

        // 【核心修复】使用和阿里云截图完全一致的通用提示信息
        messageVNode = h('div', null, [
            h('p', { style: 'font-size: 16px; color: #303133; margin: 0 0 10px 0;' }, '即将彻底删除所选文件版本。'),
            h('p', { style: 'font-size: 14px; color: #606266; margin: 0;' }, '该操作后，所有文件的历史版本和当前版本均会被删除，且无法恢复，建议谨慎操作！')
        ]);

        // API 调用逻辑保持不变，因为它需要知道具体删除什么
        if (item.is_header_row) {
            apiCall = () => apiClient.post(`/api/v1/buckets/${props.bucketName}/objects/delete-permanently`, {
                key: item.name
            });
        } else {
            apiCall = () => apiClient.post(`/api/v1/buckets/${props.bucketName}/objects/delete-version`, {
                key: item.name,
                versionId: item.version_id
            });
        }

    } else {
        // --- “隐藏历史版本”模式下的逻辑保持不变 ---
        confirmTitle = '删除文件';
        messageVNode = h('p', null, '即将删除所选文件。'); // 也转换成 VNode 保持一致
        apiCall = () => api.s3.deleteBucketItems(props.bucketName, [item.name]);
    }

    // --- 执行部分 ---
    ElMessageBox({
        title: confirmTitle,
        message: messageVNode, // 传递 VNode
        showCancelButton: true,
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        // 添加一个 class 用于微调样式 (可选)
        customClass: 'delete-confirm-dialog'
    }).then(async () => {
        try {
            await apiCall();
            ElMessage.success('操作成功！');
            fetchBucketContents();
        } catch (error) {
            ElMessage.error(error.response?.data?.error || '操作失败');
        }
    }).catch(() => ElMessage.info('已取消操作。'));
};

// handleSingleDelete 函数无需修改
// const handleSingleDelete = (row) => {
//     confirmAndDelete(row);
// };

// 在 /src/views/BucketContentsPage.vue 的 <script setup> 中

// 【最终版】替换 handleSingleDelete 和 confirmAndDelete
const handleSingleDelete = (item) => {
    if (!item) return;

    let confirmTitle = '删除';
    let messageVNode;
    let apiCall;

    // --- 1. 智能决策：根据上下文选择正确的API和提示信息 ---
    if (showVersions.value) {
        // --- 在“显示历史版本”模式下 ---
        confirmTitle = '彻底删除';

        if (item.type === 'folder') {
            // ========【核心修改 1：处理文件夹的彻底删除】========
            messageVNode = h('div', null, [
                h('p', { style: 'font-size: 16px;' }, `即将彻底删除文件夹 "${getBaseName(item.name)}"`),
                h('p', { style: 'font-size: 14px; color: #606266;' }, '该操作将删除此文件夹下的所有文件、所有历史版本和所有删除标记，且不可恢复。确定吗？')
            ]);
            // 调用我们新的“彻底批量删除”接口，并传递一个只包含该文件夹的列表
            apiCall = () => apiClient.post(`/api/v1/buckets/${props.bucketName}/delete-items-permanently`, {
                items: [item.name]
            });

        } else { // 是文件或删除标记
            // --- 这部分是您原来的、正确的逻辑，我们保留它 ---
            messageVNode = h('div', null, [
                h('p', { style: 'font-size: 16px;' }, '即将彻底删除所选文件版本。'),
                h('p', { style: 'font-size: 14px; color: #606266;' }, '该操作后，所有文件的历史版本和当前版本均会被删除，且无法恢复，建议谨慎操作！')
            ]);

            if (item.is_header_row) {
                // 如果是标题行，说明要彻底删除这个key的所有版本
                // 我们复用“彻底批量删除”接口，因为它能处理这个逻辑
                apiCall = () => apiClient.post(`/api/v1/buckets/${props.bucketName}/delete-items-permanently`, {
                    items: [item.name]
                });
            } else {
                // 如果是单个版本行，调用删除单个版本的接口
                apiCall = () => apiClient.post(`/api/v1/buckets/${props.bucketName}/objects/delete-version`, {
                    key: item.name,
                    versionId: item.version_id
                });
            }
        }

    } else {
        // --- 在“普通视图”模式下 ---
        // ========【核心修改 2：区分文件和文件夹的提示信息】========
        const itemType = item.type === 'folder' ? '文件夹' : '文件';
        confirmTitle = `删除${itemType}`;
        messageVNode = h('p', null, `确定要删除${itemType} "${getBaseName(item.name)}" 吗？`);

        // --- 这部分是您原来的、正确的逻辑，我们保留并优化 ---
        // 无论是文件还是文件夹，都统一调用“普通批量删除”接口
        apiCall = () => apiClient.post(`/api/v1/buckets/${props.bucketName}/delete-items`, {
            items: [item.name]
        });
    }

    // --- 2. 统一的确认和执行流程 (这部分是您原来的代码，无需修改) ---
    ElMessageBox({
        title: confirmTitle,
        message: messageVNode,
        showCancelButton: true,
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
    }).then(async () => {
        const loading = ElLoading.service({ text: '正在操作...' });
        try {
            await apiCall();
            ElMessage.success('操作成功！');
        } catch (error) {
            // ElMessage.error(error.response?.data?.error || '操作失败');
        } finally {
            loading.close();
            fetchBucketContents();
        }
    }).catch(() => {
        ElMessage.info('已取消操作。');
    });
};



// =========================================================================
// ==    请用下面的 handleBatchDelete 函数，替换您现有的同名函数    ==
// =========================================================================
const handleBatchDelete = async () => {
    const itemsToDelete = selectedItems.value; // 直接使用原始勾选列表
    if (itemsToDelete.length === 0) {
        ElMessage.warning('请选择要删除的项目。');
        return;
    }

    const confirmTitle = showVersions.value ? '批量彻底删除' : '批量删除';
    const message = `确定要删除选中的 ${itemsToDelete.length} 个项目吗？` + (showVersions.value ? '此操作将彻底删除所有历史版本且不可恢复。' : '');

    try {
        await ElMessageBox.confirm(message, confirmTitle, { /* ... */ });
    } catch (e) {
        ElMessage.info('已取消批量删除操作。');
        return;
    }

    const loading = ElLoading.service({ text: `正在删除...` });

    // 【核心修复：根据上下文调用不同的API】
    const items = itemsToDelete.map(item => item.name);
    let apiCall;

    if (showVersions.value) {
        // 在版本视图下，调用“彻底删除”接口
        apiCall = apiClient.post(`/api/v1/buckets/${props.bucketName}/delete-items-permanently`, { items });
    } else {
        // 在普通视图下，调用“普通删除”接口
        apiCall = apiClient.post(`/api/v1/buckets/${props.bucketName}/delete-items`, { items });
    }

    try {
        await apiCall;
        ElMessage.success('操作成功！');
    } catch (error) {
        ElMessage.error(error.response?.data?.error || '操作失败');
    } finally {
        loading.close();
        fetchBucketContents();
    }
};

// 【新增】这个新函数
const handleToggleVersions = (newValue) => {
    router.push({
        query: { ...route.query, versions: newValue ? 'true' : undefined }
    })
};

/**
 * 【最终版】处理单个恢复操作，由 ObjectTable 组件 emit 事件触发
 * @param {object} item - 被点击行的数据对象
 */
const handleRestore = async (item) => {
    // 这里我们直接调用 API，因为 ObjectTable 内部已经处理了加载状态
    // 我们不再需要在这里管理 loading 状态
    try {
        await apiClient.post(`/api/v1/buckets/${props.bucketName}/objects/restore-version`, {
            key: item.name,
            versionId: item.version_id,
        });

        ElMessage.success('版本已成功恢复！');

        // 操作成功后，刷新列表
        fetchBucketContents();

    } catch (error) {
        console.error(`恢复操作失败:`, error);
        // 错误提示由 ObjectTable 内部处理，这里可以不再重复提示
        // 或者您也可以在这里统一处理错误
        const errorMessage = error.response?.data?.error || '操作失败，请重试';
        ElMessage.error(errorMessage);
    }
};


/**
 * 【最终版】处理批量恢复操作，由 ObjectBatchActionBar 组件 emit 事件触发
 */
const handleBatchRestore = async () => {
    // 1. 过滤出真正需要恢复的项目
    const itemsToRestore = selectedItems.value.filter(
        item => item.type === 'delete_marker' || (item.type === 'file' && !item.is_latest)
    );

    if (itemsToRestore.length === 0) {
        ElMessage.info('没有选中任何可恢复的版本。');
        return;
    }

    // 2. 显示全局加载动画
    const loading = ElLoading.service({ text: `正在批量恢复 ${itemsToRestore.length} 个版本...` });

    let successCount = 0;
    let failCount = 0;

    // 3. 循环调用 API
    for (const item of itemsToRestore) {
        try {
            await apiClient.post(`/api/v1/buckets/${props.bucketName}/objects/restore-version`, {
                key: item.name,
                versionId: item.version_id,
            });
            successCount++;
        } catch (error) {
            failCount++;
            console.error(`恢复 ${item.name} (版本 ${item.version_id}) 失败:`, error);
        }
    }

    // 4. 关闭加载并显示最终结果
    loading.close();

    ElNotification({
        title: '批量恢复完成',
        message: `成功: ${successCount}, 失败: ${failCount}. ${failCount > 0 ? '失败详情请查看控制台。' : ''}`,
        type: successCount > 0 && failCount === 0 ? 'success' : 'warning',
        duration: 5000,
    });

    // 5. 统一刷新列表
    fetchBucketContents();
};

const openFragmentManagementDrawer = () => {
    // a. 先把抽屉打开
    isFragmentDrawerVisible.value = true;

    // b. 【关键】通过 ref 调用子组件暴露出来的方法
    //    使用 nextTick 确保在DOM更新、子组件被渲染出来之后再调用
    import('vue').then(({ nextTick }) => {
        nextTick(() => {
            if (fragmentDrawerRef.value) {
                console.log('[BucketContentsPage] Calling child component method fetchFragments...');
                fragmentDrawerRef.value.fetchFragments();
            } else {
                console.error('[BucketContentsPage] fragmentDrawerRef is not available!');
            }
        });
    });
};

// 【替换】用下面的 watch 逻辑替换你现有的 watch
watch(
    () => props.bucketName,
    (newBucketName) => {
        if (newBucketName) {
            // 当 Bucket 名称变化时（即从一个桶导航到另一个桶），
            // 重置所有状态并重新获取所有数据。
            showVersions.value = false;
            searchPrefix.value = '';
            pagination.value.currentPage = 1;
            fetchBucketDetails(); // <-- 获取新桶的版本状态
            fetchBucketContents();
        }
    },
    { immediate: true } // 立即执行，确保首次加载页面时触发
);

watch(
    // 监听路由的完整路径（包括参数和查询）
    () => route.fullPath,
    () => {
        // 当URL发生任何变化时（进入新目录、切换版本显示、翻页等）
        // 1. 同步 showVersions 的状态
        showVersions.value = route.query.versions === 'true';
        // 2. 重新获取数据
        fetchBucketContents();
    },
    { immediate: true } // 立即执行，确保首次加载页面时触发
);

onMounted(() => {
    fetchBucketDetails();
    // fetchBucketContents 会被上面的 watcher 在 immediate: true 时自动调用，所以这里可以移除
});
</script>

<!-- /src/views/BucketContentsPage.vue -->

<style scoped>
/* 父组件现在只需要最基本的页面布局和导航栏样式 */

.bucket-contents-page {
    background-color: #fff;
    padding: 20px;
}

/* 导航栏样式保留，因为它仍在父组件的模板中 */
.unified-nav-bar {
    display: flex;
    align-items: center;
    margin-bottom: 20px;
}

.back-button-unified {
    padding: 0;
    margin-right: 8px;
    font-size: 20px;
    min-height: auto;
    border: none;
    background-color: transparent;
}

.unified-nav-bar .el-breadcrumb {
    font-size: 18px;
}

.unified-nav-bar .el-breadcrumb :deep(.el-breadcrumb__separator) {
    vertical-align: middle;
}
</style>